Со временем, у каждого разработчика возникает вопрос, куда записывать служебную информацию ? Всевозможные настройки интерфейса, индивидуальные данные для пользователей и т.п. Одни пишут это в текстовые файлы, другие сохраняют переменные памяти в файлах и т.д.
Мы уже увидели, что VFP хранит очень много служебной информации в таблицах. Даже библиотеки классов - таблицы.
Пора и нам создать свою собственную базу данных для системной информации нашего приложения. Создаем папку System(если она еще не создана) в папке нашего проекта. В окне проекта на закладке Data создаем базу данных D_SYSTEM. Добавляем в нее таблицу T_Registry следующей структуры:
| Наименование | Тип | Ширина | Десятичные знаки | |
|---|---|---|---|---|
| FldStrKey | Char | 100 | Ключ поиска | |
| FldStrType | Char | 1 | Тип данных | |
| FldStr | Char | 250 | Строка данных | |
| FldInt | Int | Целое число | ||
| FldLog | Log | Логическое | ||
| FldDateTime | DateTime | Дата и время | ||
| FldNum | Num | 20 | 6 | Цифровое |
| FldIntIdentity | Int | Уникальный код |
По полю FldStrKey необходимо создать индекс с именем TAG_KEY типа Primary, чтобы обеспечить уникальность записей. Об индексах расскажу далее.
Чем наше приложение хуже Windows !!! У нас теперь есть свой реестр. Для работы с ним создадим несколько функций.
Прежде, чем что-то получить, его надо записать. Пишем функцию SetRegistry():
*
* function SetRegistry
* передаем в функцию ключ, тип и значение
lparameters strLocPrmKey, strLocPrmType, voidLocPrmValue
*
local logLocReturn, strLocKey
logLocReturn = .F.
* преобразовываем строку ключа в верхний регистр
* и дополняем пробелами до длины поля FldStrKey,
* предварительно, функцией alltrim() убираем возможные
* пробелы (ошибки при написании кода)
strLocKey = padr(upper(alltrim(strLocPrmKey)),100)
* открываем таблицу или проверяем, что она открыта (см. ниже)
if (OpenTable(".\System\T_Registry.DBF", "AliasSystemRegistry") > 0)
* проверяем наличие ключа в таблице самым быстрым способом
* для файл-серверного варианта нашего приложения
* если нет такой записи - добавляем ее
if .not. seek(strLocKey,"AliasSystemRegistry","TAG_KEY")
insert into AliasSystemRegistry (FldStrKey, FldStrType) ;
values (strLocPrmKey, strLocPrmType)
endif
* проверяем ключ
if (AliasSystemRegistry.FldStrKey = strLocKey)
* записываем наши данные в реестр
do case
case strLocPrmType = "C"
replace FldStr with voidLocPrmValue
case strLocPrmType = "I"
replace FldInt with voidLocPrmValue
case strLocPrmType = "L"
replace FldLog with voidLocPrmValue
case strLocPrmType = "N"
replace FldNum with voidLocPrmValue
case strLocPrmType = "D"
replace FldDateTime with voidLocPrmValue
endcase
* возвращаем TRUE
logLocReturn = .T.
endif
endif
return logLocReturn
*
К системному реестру нашего приложения мы будем обращаться постоянно. Поэтому, псевдоним задаем постоянный, а не получаем функцией GetNewAlias(). Функцию OpenTable() необходимо дополнить кодом проверки открытого псевдонима с возвратом рабочей области :
*
#INCLUDE .\Include \Define.H
*
* function OpenTable
* передаем имя таблицы или путь к ней и псевдоним
lparameters strLocPrmTable, strLocPrmAlias
local intLocReturnWorkArea, intLocCount, objLocWorkArea
* инициализируем код возврата
intLocReturnWorkArea = 0
* проверка псевдонима
if used(strLocPrmAlias)
* инициализируем код возврата номером рабочей области
intLocReturnWorkArea = select(strLocPrmAlias)
else
* весь предыдущий код
::::::
:::..
endif
return intLocReturnWorkArea
*
Теперь пишем функцию чтения из реестра GetRegistry():
*
* function GetRegistry
lparameters strLocPrmKey, strLocPrmType, voidLocPrmValue
local voidLocReturn, strLocKey
strLocKey = padr(upper(alltrim(strLocPrmKey)),100)
if (OpenTable(".\System\T_Registry.DBF", "AliasSystemRegistry") > 0)
if .not. seek(strLocKey,"AliasSystemRegistry","TAG_KEY")
* если нет записи - используем функцию SetRegistry() !!!
SetRegistry(strLocPrmKey, strLocPrmType, voidLocPrmValue)
endif
if (AliasSystemRegistry.FldStrKey = strLocKey)
* читаем наши данные из реестра и записываем в переменную возврата
do case
case strLocPrmType = "C"
voidLocReturn = AliasSystemRegistry .FldStr
case strLocPrmType = "I"
voidLocReturn = AliasSystemRegistry .FldInt
case strLocPrmType = "L"
voidLocReturn = AliasSystemRegistry .FldLog
case strLocPrmType = "N"
voidLocReturn = AliasSystemRegistry .FldNum
case strLocPrmType = "D"
voidLocReturn = AliasSystemRegistry .FldDateTime
endcase
endif
endif
return voidLocReturn
*
Теперь мы имеем возможность сохранять любые наши данные. Функциональность таблицы T_REGISTRY можно расширить добавлением соответствующих полей. Примеры использования:
* при входе пользователя в программу
GetRegistry("User001.MainWindow.Top","I",0)
GetRegistry("User001.MainWindow.Left","I",0)
GetRegistry("User001.MainWindow.Height","I",400)
GetRegistry("User001.MainWindow.Width","I",400)
GetRegistry("User001.LastDate","D",datetime())
* при выходе пользователя из программы
SetRegistry("User001.MainWindow.Top","I",_SCREEN.Top)
SetRegistry("User001.MainWindow.Left","I",_SCREEN.Left)
SetRegistry("User001.MainWindow.Height","I",_SCREEN.Height)
SetRegistry("User001.MainWindow.Width","I",_SCREEN.Width)
SetRegistry("User001.LastDate","D",datetime())
*
Обратите внимание, что наш реестр самозаполняемый !!! Вы можете использовать функцию GetRegistry() без предварительной записи ключей, а значение (третий параметр) будет значением по умолчанию !!!